package Control;
import java.security.Timestamp;
import java.util.Scanner;
import java.math.*;
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.io.*;
/*
 * 利用所学知识，制作一个简易的词汇掌握问答得分系统
 */
public class List_Test {
    private String word[];//用于存储词汇的数组
    private String chinese[];//用于存储word词汇数组对应的每个单词的含义
    private String wordfault[];//用于存储测试中答错词汇的数组
    private String chinesefault[];//用于存储测试中答错词汇含义的数组
    private int mark[];//用于标记当前词汇数组是否被访问
    private int markfault[];//用于标记答错词汇数组是否被访问
    private int removemark[];//用于判别当前答对的错题词汇是否可从错题库中移除
    private int n;//用于标识当前词汇数组的容量
    private int count;//用于表示当前答错词汇数组的容量
    private int maxSize;//用于规定词汇数组的最大容量
    private double score;//用于计算当前测试者的得分
    private int pass;//用于计算当前测试者测试成绩及格的次数
    private int fail;//用于计算当前测试者测试成绩不及格的次数
    private Timestamp TIME;//用于计算测试者本次测试的耗时
    public List_Test(String filePath) throws IOException{//构造器从指定文件路径中读取装载数据
    	int n = data_loading(filePath);
    	//各变量初始化
    	mark = new int[n];
    	wordfault = new String[n];
    	chinesefault = new String[n];
    	markfault = new int[n];
    	removemark = new int[n];
    	score = 0;
    	pass = fail = 0;
    }
    public boolean checkChinese(String x,int p,int option){
    	int count = 0;//用于记录测试者回答的单词正确含义的个数，只有当全部回答对之后才能得分
    	int flag = 0;//flag用于标记测试者回答的单词正确含义字符串中是否带有","
    	String Str[] = null;//Str数组用于存储下标为p的chinese[p]或chinesefault[p]以","分隔的词义数组
    	switch(option){//option变量记录了fault变量的值,根据option的值进行不同的操作
    	case 0 : 
    		Str = chinese[p].split(",");break;
    	case 1 :
    		Str = chinesefault[p].split(",");break;
    	}
    	int N = Str.length;//N变量用于记录Str数组的长度
    	//字符串变量x用于记录用户在应答界面输入的字符串
    	if(x.indexOf(",") != -1)//若x字符串中有符号",",意味着用户输入了多个词义,则需判断用户输入的词义是否全部答对
    	{
    		flag = 1;
    	    String str[] = x.split(",");//str数组用于存储字符串x以","分隔的词义数组
    	     n = str.length;//整型变量n用于记录str数组的长度
    	    for(int i = 0; i < n; i++){//在Str数组里检索是否存在与str数组匹配的词义
    	    	for(int j = 0; j < N; j++){
    	    		if(str[i].equals(Str[j])){
    	    			count++;//整型变量count用于记录匹配的词义个数
    	    			break;
    	    		}
    	    	}
    	    }
    	    if(count == n) return true;//若count与str数组长度相同,则说明用户回答正确,返回true
    	}
    	else{//若x字符串中没有符号",",意味着用户只输入了单个词义,则只需判断用户输入的唯一一个词义是否答对
    	for(int i = 0; i < N; i++){
    		if(x.equals(Str[i])){
    			count++;
    			break;
    		}
    	}
    	if(count == 1) return true;
    	}
    	return false;
    }
    public void testInterval(int choose,int unit,int fault){//testInterval为测试中间函数,防止主test方法中代码冗余不利于开发者品读
    	Scanner sc = new Scanner(System.in);//构建输入器sc
    	int n = word.length;//整型变量n用户记录当前word数组的词汇容量
    	System.out.println("请输入要测试的词汇个数:" + "(当前错题库中词汇数量为:" + count + "个)");
    	int k = sc.nextInt();//整型变量k用于记录用户此次测试要输入的词汇个数
        int order_number = 0;//整型变量order_number用于记录用户当前测试的词汇序号
        while(order_number < k){
     	   order_number++;
     	   int i = 0;//整型变量i用于标记提供给用户测试的词汇在词汇数组中的下标
     	     while(true){
     	     switch(choose){//整形变量choose用于标记当前用户进行的测试模式,choose的值为1时为单元测试,2为全真测试,3为错题测试
     	     case 1: 
     	    	 while(true){
     	    	 i = (unit*100-1) - (int)(100*Math.random()); //生成(unit-1)*100-1~到unit*100的下标
     	    	 if(i <= n) break;//若下标大于n,则表示出错,需重新生成
     	    	 }
     	    	 break;
     	     case 2:
     	    	 i = (int)(n*Math.random());//生成0~(n-1)的下标
     	    	 break;
     	     case 3:
     	    	 i = (int)(count*Math.random());//生成0~(count-1)的下标
     	    	 break;
     	     }
     	      if(fault == 0){//整型变量fault表示当前生成的词汇出自于词库词汇还是错题库词汇,  
     	    //falut的值为0表示出自于词库词汇,为1时表示出自于错题库词汇
     		  if(mark[i] != -1){
     		  mark[i] = -1;
     		  break;
     		  }
     	      }
     	      else {
     	      if(markfault[i] != -1){
     	    	  markfault[i] = -1;
     	    	  break;
     	      }
     	      }
     	     }
     	   System.out.print(order_number + "、");
     	   switch(fault){
     	   case 0:
     		   System.out.println(word[i] + ":");
     		   break;
     	   case 1:
     		   System.out.println(wordfault[i] + ":");
     		   break;
     	   }
     	   String x = sc.next();//字符串变量x用于记录用户输入的应答字符串
     	   if(checkChinese(x,i,fault)){//调用checkChinese方法判别用户是否回答正确
     		   score += (100/k);//回答正确则得取相应分数
     		   System.out.print("恭喜你答对了,");
     		   switch(fault){//当fault的值为1时,调用faultRemove方法判别是否可移除错题
     		   case 0:break;
     		   case 1:faultmarkAddition(i);break;
     		   }
     	   }
     	   else 
     		   {
     		   switch(fault){//当fault的值为0时,将当前用户应答的词汇添加至错题词库,为1时,不做添加操作
     		   case 0 :
     			   System.out.print("很遗憾你答错了," + word[i] + "的正确含义为:" + chinese[i] + "。");
     			   faultAddition(word[i],chinese[i]);
     			   break;
     		   case 1 :
     			   System.out.print("很遗憾你答错了," + wordfault[i] + "的正确含义为:" + chinesefault[i] + "。");
    			   break;  
     		   }
     		   }
     	   System.out.println("当前得分为:" + (int)score + ",请输入任意字符串继续测试、输入-1终止测试");
     	   x = sc.next();
     	   if(x == "-1") break;
     } 
     
        if(score == 100){
     	   System.out.println("恭喜您已经到达了炉火纯青、登峰造极的境界，请继续保持~");
     	   pass += 1;
     	   }    
        else if(score >= 80 && score < 100){
     	   System.out.println("奈斯！本次测试的得分为: " + (int)score + ",再接再厉哦！");
     	   pass += 1;
        }
        else if(score >= 60 && score < 80){
        System.out.println("不错！本次测试的得分为：" + (int)score + ",继续努力吧。");
        pass += 1;
        }
        else if(score < 60){
     	   System.out.print("哎呀，本次测试的得分为: " + (int)score + ",再加把劲吧。  " + " ");
        fail += 1;
        }
        }
    public void test() throws AWTException{//测试方法
    	int n = word.length;
       Scanner sc = new Scanner(System.in);
       while(true){
       long time1 = System.currentTimeMillis();//长整型变量time1用于记录测试开始时的时间
       System.out.println("当前您的测试通过与失败的次数分别为——" + pass + ":" + fail);
       System.out.println("请输入您当前所需要进行的操作：1、参加测试，测试总分共100分，60分为合格线。=∨="
       		+ " 2、退出测试，放弃学习机会>-<。");
       int choose1 = sc.nextInt();
       if(choose1 == 2) return;
       System.out.println("请输入要测试的模式:1、单元测试。2、全真测试。 3、错题测试");
       int choose2 = sc.nextInt();
       int unit = 0;
       int fault = 0;
       switch(choose2){
       case 1:
    	   System.out.println("目前可测试的单元为Unit1~Unit" + (n/100 + 1) + "。请输入要测试的单元:");
    	   unit = sc.nextInt();
    	   testInterval(choose2,unit,fault);
    	   break;
       case 2:
    	   testInterval(choose2,unit,fault);
    	   break;
       case 3:
    	   fault = 1;
    	   testInterval(choose2,unit,fault); 
           break;
       }
       long time2 = System.currentTimeMillis();//长整型变量time2用于记录测试结束时的时间
       int time = (int)(time2 - time1)/1000;//整型变量time用于记录本次测试的使用时间,精确到分/秒制方式记录(min/s)
       if(time >= 60) {
    	   System.out.println("本次测试耗时" + time/60 + "分" + (time - 60*(time/60)) + "秒");
       }
       else {
    	   System.out.println("本次测试耗时" + time + "秒");
       }
       System.out.println("是否继续测试？  是:1 否:0");
       int option = sc.nextInt();
       if(option == 1){
        cleanMark();
        cleanScore();
        faultRemove();
        clearScreen();   
       }
       
       else break;
       }
    }
    
    public void faultAddition(String word,String chinese){//错题库错题添加方法
    	for(int i = 0;i < count; i++){//检索此次添加的错题词汇在错题库中是否存在
    		if(wordfault[i].equals(word))
    			return;
    	}
    	wordfault[count] = word;
    	chinesefault[count] = chinese;
    	count++;
    }
    
    public void faultmarkAddition(int p){
    	removemark[p]++;
    }
    public void faultRemove(){//错题从错题库中移除方法
    	for(int p = 0;p < count;){
    	if(removemark[p] >= 3){//当用户答对错题三次以上时,将错题从错题库中移除
    	for(int i = p;i < count - 1; i++){
    		wordfault[i] = wordfault[i+1];
    		chinesefault[i] = chinesefault[i+1];
    		removemark[i] = removemark[i+1];
    	}
    	count --;
    	continue;
    	}
       p++;
    }
	}

    public void cleanMark(){ //清除标记数组
    	for(int i = 0; i < n; i++){
    		mark[i] = 0;
    		markfault[i] = 0;
    	}
       }
    
    public void cleanScore(){ //清除分数
    	score = 0;
    }
     public int data_loading(String filePath) throws IOException{//词汇装载方法
     BufferedReader br = new BufferedReader(new InputStreamReader(
		   new FileInputStream(filePath)));
         String str1[] = new String[1000];
         for (String line = br.readLine(); line != null; line = br.readLine()){ 
        	str1[n++] = line;
         }
    	 word = new String[n];
    	 chinese = new String[n];
    	 for (int i = 0; i < n; i++){
    		 String str2[] = str1[i].split("——");
    		 word[i] = str2[0];
    		 chinese[i] = str2[1];
    	 }   	 
    	 return n;
    	 
     }
     public void data_writer(String filePath) throws IOException {//录入词汇方法
    	 FileWriter FW = new FileWriter(filePath,true);
    	 /*
 		 * FileWritter, 字符流写入字符到文件。默认情况下，它会使用新的内容取代所有现有的内容，然而，
 		 * 当指定一个true （布尔）值作为FileWritter构造函数的第二个参数，它会保留现有的内容，
 		 * 并追加新内容在文件的末尾。
 		 */
    	 Scanner sc = new Scanner(System.in);
    	 System.out.println("请输入要录入的词汇个数:");
    	 int n = sc.nextInt();
    	 for(int i = 0;i < n; i++){	
    		 String data = sc.next();
    		 data += sc.nextLine();
    		 FW.write("\r" + data);
    	 }
    	 //next()方法是以换行或者空格符为分界线接收下一个String类型变量，
    	 //不过并没有提取换行或者空格，所以生成的data并不包含换行。
    	 FW.close();
    	 
     }
     
     public void clearScreen() throws AWTException{
    	 //生成一个图形化界面机器人,帮助主人进行相应操作
    	 Robot r = new Robot();
    	 r.mousePress(InputEvent.BUTTON3_MASK); //按下鼠标右键
    	 r.mouseRelease(InputEvent.BUTTON3_MASK);//释放鼠标右键
    	 r.keyPress(KeyEvent.VK_CONTROL); //按下Ctrl键
    	 r.keyPress(KeyEvent.VK_R); //按下R键
    	 r.keyRelease(KeyEvent.VK_R); //释放R键
    	 r.keyRelease(KeyEvent.VK_CONTROL);//释放CTRL键
    	 r.delay(100);//暂停100ms后刷新
     }
	public static void main(String[] args) throws IOException, AWTException {
		String filePath = "word/word.txt";
		List_Test List = new List_Test(filePath);
		List.data_writer(filePath);
		List.test();
	}

}